/*
 * Copyright (C) 2020  Prasoon Joshi
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public License
 *     along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package graphql

import graphql.SchemaDefinition._
import sangria.schema._

object SchemaUnions {
  lazy val MixedBasicElementsTypeList = List(FreeTextType, AbbrType, EmphType, ExpanType, ForeignType, LbType, PtrType, RefType)

  lazy val AccessTypesList = List(PersnameType, CorpnameType, FamnameType, GeognameType, NameType, OccupationType,
    SubjectType, GenreformType, FunctionTypeType, TitleType)

  lazy val InterNoquoteElementsTypeList = List(ChronlistType, ListTypeType, TableType)

  lazy val InterElementsTypeList = InterNoquoteElementsTypeList :+ BlockquoteType

  lazy val BlocksElementsTypeList = InterElementsTypeList :+ PType

  implicit lazy val MixedBasicPlusAccessibleOptionType: UnionType[Unit] =
    UnionType(
      "MixedBasicPlusAccessibleOptions",
      Some("A union of m.mixed.basic.elements, m.access, date, footnote, num ,quote"),
      types = MixedBasicElementsTypeList ++ AccessTypesList ++ List(DateType, FootnoteType, NumType, QuoteType)
    )

  implicit val MixedBasicElementsOptionType: UnionType[Unit] =
    UnionType(
      "MixedBasicElementsOption",
      Some("A union type for all MixedBasicElementsOption types"),
      types = MixedBasicElementsTypeList
    )

  implicit lazy val DatesetOptionType: UnionType[Unit] =
    UnionType(
      "DatesetOption",
      Some("A union of Daterange and Datesingle"),
      types = List(DatesingleType, DaterangeType)
    )

  implicit lazy val DatesetOption2Type: UnionType[Unit] =
    UnionType(
      "DatesetOption2",
      Some("A union of Datesingle and Daterange"),
      types = List(DatesingleType, DaterangeType)
    )

  implicit lazy val ParaContentableOptionType: UnionType[Unit] =
    UnionType(
      "ParaContentableOption",
      Some("A union of paragraph content options"),
      types = List(FreeTextType, AbbrType, CorpnameType, DateType, EmphType, ExpanType, FamnameType, FootnoteType, ForeignType,
        FunctionTypeType, GenreformType, GeognameType, LbType, ListTypeType, NameType, NumType, OccupationType,
        PersnameType, PtrType, QuoteType, RefType, SubjectType, TitleType)
    )

  implicit lazy val ArchDescOptionType: UnionType[Unit] =
    UnionType(
      "ArchDescOption",
      Some("A union of all types that make up Archive Description Options"),
      types = List(AccessrestrictType, AccrualsType, AcqinfoType, AltformavailType, AppraisalType, ArrangementType,
        BibliographyType, BioghistType, ControlaccessType, CustodhistType, FileplanType, IndexType, LegalstatusType,
        OddType, OriginalslocType, OtherfindaidType, PhystechType, PreferciteType, ProcessinfoType, RelatedmaterialType,
        RelationsType, ScopecontentType, SeparatedmaterialType, UserestrictType, DscType)
    )

  implicit lazy val AccessRestrictOptionType: UnionType[Unit] =
    UnionType(
      "AccessRestrictOptions",
      Some("A union of all types that make up AccessRestrictOptions"),
      types = List(AccessrestrictType, BlockquoteType, ChronlistType, HeadType, ListTypeType, PType, TableType)
    )

  implicit lazy val BlockQuoteOptionType: UnionType[Unit] =
    UnionType(
      "BlockQuoteOptions",
      Some("A union of all types that make up BlockquoteOptions"),
      types = List(ChronlistType, ListTypeType, PType, TableType)
    )

  implicit lazy val MixedBasicElementsOption1Type: UnionType[Unit] =
    UnionType(
      "MixedBasicElementsOption1",
      Some("A union of mixedBasicElementsOption1 types."),
      types = List(FreeTextType, AbbrType, EmphType, ExpanType, ForeignType, LbType, PtrType, RefType)
    )

  implicit lazy val ChronItemOptionType: UnionType[Unit] =
    UnionType(
      "ChronItemOptions",
      Some("A union of chronitem options"),
      types = List(DaterangeType, DatesetType, DatesingleType)
    )

  implicit lazy val ChronItemOption2Type: UnionType[Unit] =
    UnionType(
      "ChronItemOption2",
      Some("A union of event or set of events"),
      types = List(ChronitemsetType, EventType, GeognameType)
    )

  implicit lazy val ListTypeOptionType: UnionType[Unit] =
    UnionType(
      "ListTypeOptions",
      Some("A union of Item, Listhead and Defitem"),
      types = List(ItemType, ListTypeSequence1Type)
    )

  implicit lazy val AccrualsOptionType: UnionType[Unit] =
    UnionType(
      "AccrualsOptions",
      Some("A union of accruals option types"),
      types = List(AccrualsType, BlockquoteType, ChronlistType, HeadType, ListTypeType, PType, TableType)
    )

  implicit lazy val AcqInfoOptionType: UnionType[Unit] =
    UnionType(
      "AcqInfoOptions",
      Some("A union of acquisition info option types"),
      types = List(AcqinfoType, BlockquoteType, ChronlistType, HeadType, ListTypeType, PType, TableType)
    )

  implicit lazy val AltFormAvailOptionType: UnionType[Unit] =
    UnionType(
      "AltFormAvailOptions",
      Some("A union of AltFormAvail Option types"),
      types = List(AltformavailType, BlockquoteType, ChronlistType, HeadType, ListTypeType, PType, TableType)
    )

  implicit lazy val AppraisalOptionType: UnionType[Unit] =
    UnionType(
      "AppraisalOptions",
      Some("A union of all appraisal option types"),
      types = List(AppraisalType, BlockquoteType, ChronlistType, HeadType, ListTypeType, PType, TableType)
    )

  implicit lazy val ArrangementOptionType: UnionType[Unit] =
    UnionType(
      "ArrangementOptions",
      Some("A union of all arrangement option types"),
      types = List(ArrangementType, BlockquoteType, ChronlistType, HeadType, ListTypeType, PType, TableType)
    )

  implicit lazy val BibliographyOptionType: UnionType[Unit] =
    UnionType(
      "BibliographyOptions",
      Some("A union of all Bibliography option types"),
      types = List(ArchrefType, BibliographyType, BibrefType, BlockquoteType, ChronlistType, HeadType, ListTypeType, PType, TableType)
    )

  implicit lazy val BiogHistOptionType: UnionType[Unit] =
    UnionType(
      "BiogHistOptions",
      Some("A union of all BiogHist option types"),
      types = List(BioghistType, BlockquoteType, ChronlistType, HeadType, ListTypeType, PType, TableType)
    )

  implicit lazy val ControlAccessOptionType: UnionType[Unit] =
    UnionType(
      "ControlAccessOptions",
      Some("A union of all ControlAccess option types"),
      types = List(ControlaccessType, BlockquoteType, ChronlistType, HeadType, ListTypeType, PType, TableType,
        CorpnameType, FamnameType, FunctionTypeType, GenreformType, GeognameType, NameType, OccupationType, PersnameType,
        SubjectType, TitleType)
    )

  implicit lazy val CustodHistOptionType: UnionType[Unit] =
    UnionType(
      "CustodHistOptions",
      Some("A union of all CustodHist option types"),
      types = List(CustodhistType, BlockquoteType, ChronlistType, HeadType, ListTypeType, PType, TableType)
    )

  implicit lazy val FilePlanOptionType: UnionType[Unit] =
    UnionType(
      "FilePlanOptions",
      Some("A union of all FilePlan option types"),
      types = List(FileplanType, BlockquoteType, ChronlistType, HeadType, ListTypeType, PType, TableType)
    )

  implicit lazy val IndexOptionType: UnionType[Unit] =
    UnionType(
      "IndexOptions",
      Some("A union of all Index option types"),
      types = List(IndexType, IndexentryType, ListheadType)
    )

  implicit lazy val IndexEntryOptionType: UnionType[Unit] =
    UnionType(
      "IndexEntryOption",
      Some("A union of all indexEntry option types"),
      types = List(NamegrpType, CorpnameType, FamnameType, FunctionTypeType, GenreformType, GeognameType, NameType,
        OccupationType, PersnameType, SubjectType, TitleType)
    )

  implicit lazy val AccessType: UnionType[Unit] =
    UnionType(
      "AccessTypes",
      Some("A union of all access types"),
      types = List(CorpnameType, FamnameType, FunctionTypeType, GenreformType, GeognameType, NameType, OccupationType,
        PersnameType, SubjectType, TitleType)
    )

  implicit lazy val IndexEntryOption2Type: UnionType[Unit] =
    UnionType(
      "IndexEntryOption2",
      Some("A union of PtrGrp and Refs"),
      types = List(PtrgrpType, PtrType, RefType)
    )

  implicit lazy val RefsOptionsType: UnionType[Unit] =
    UnionType(
      "RefOptions",
      Some("A union of refs options"),
      types = List(PtrType, RefType)
    )

  implicit lazy val LegalStatusOptionType: UnionType[Unit]=
    UnionType(
      "LegalStatusOption",
      Some("A union of LegalStatus and blocks"),
      types = BlocksElementsTypeList :+ LegalstatusType
    )

  implicit lazy val OddOptionType: UnionType[Unit] =
    UnionType(
      "OddOptions",
      Some("A union of blocks and Odd types"),
      types = BlocksElementsTypeList :+ OddType
    )

  implicit lazy val OriginalsLocOptionType: UnionType[Unit] =
    UnionType(
      "OriginalsLocOptions",
      Some("A union of m.blocks and OriginalsLoc types"),
      types = BlocksElementsTypeList :+ OriginalslocType
    )

  implicit lazy val OtherFindAidOptionType: UnionType[Unit] =
    UnionType(
      "OtherFindAidOptions",
      Some("A union of m.blocks, otherfindaid, archref and bibref types"),
      types = BlocksElementsTypeList ++ List(OtherfindaidType, ArchrefType, BibrefType)
    )

  implicit lazy val PhysTechOptionType: UnionType[Unit] =
    UnionType(
      "PhysTechOptions",
      Some("A union of m.blocks and phystech types"),
      types = BlocksElementsTypeList :+ PhystechType
    )

  implicit lazy val PrefereCiteOptionType: UnionType[Unit] =
    UnionType(
      "PreferCiteOptions",
      Some("A union of m.blocks and preferCite types"),
      types = BlocksElementsTypeList :+ PreferciteType
    )

  implicit lazy val ProcessInfoOptionType: UnionType[Unit] =
    UnionType(
      "ProcessInfoOption",
      Some("A union of m.blocks and processInfo types"),
      types = BlocksElementsTypeList :+ ProcessinfoType
    )

  implicit lazy val RelatedMaterialOptionType: UnionType[Unit] =
    UnionType(
      "RelatedMaterialOption",
      Some("A union of m.blocks, relatedMaterial, archref and bibref types"),
      types = BlocksElementsTypeList ++ List(RelatedmaterialType, ArchrefType, BibrefType)
    )

  implicit lazy val RelationOptionType: UnionType[Unit] =
    UnionType(
      "RelationOptions",
      Some("A Union of datesingle, daterange and dateset types"),
      types = List(DatesingleType, DaterangeType, DatesetType)
    )

  implicit lazy val ScopeContentOptionType: UnionType[Unit] =
    UnionType(
      "ScopeContentOptions",
      Some("A union of m.blocks and scopeContent types"),
      types = BlocksElementsTypeList :+ ScopecontentType
    )

  implicit lazy val SeparatedMaterialOptionType: UnionType[Unit] =
    UnionType(
      "SeparatedMaterialOption",
      Some("A union of m.blocks, separatedMaterial, archref and bibref types"),
      types = BlocksElementsTypeList ++ List(SeparatedmaterialType, ArchrefType, BibrefType)
    )

  implicit lazy val UseRestrictOptionType: UnionType[Unit] =
    UnionType(
      "UseRestrictOptions",
      Some("A union of m.blocks and useRestrict types"),
      types = BlocksElementsTypeList :+ UserestrictType
    )

  implicit lazy val DidOptionType: UnionType[Unit] =
    UnionType(
      "DidOptions",
      Some("A union of abstract, container, dao, daoset, didnote, head, langmaterial, materialspec, origination, " +
        "physdescset, physdesc, physdescstructured, physloc, repository, unitdate, unitdatestructured, unitid, " +
        "unittitle types"),
      types = List(AbstractType, ContainerType, DaoType, DaosetType, DidnoteType, LangmaterialType,
        MaterialspecType, OriginationType, PhysdescsetType, PhysdescType, PhysdescstructuredType, PhyslocType,
        RepositoryType, UnitdateType, UnitdatestructuredType, UnitidType, UnittitleType)
    )

  implicit lazy val LangMaterialOptionType: UnionType[Unit] =
    UnionType(
      "LangMaterialOption",
      Some("A union of language and languageset types"),
      types = List(LanguageType, LanguagesetType)
    )

  implicit lazy val OriginationOptionType: UnionType[Unit] =
    UnionType(
      "OriginationOptions",
      Some("A union of Corpname, Famname, Name, Persname types"),
      types = List(CorpnameType, FamnameType, NameType, PersnameType)
    )

  implicit lazy val PhysDescStructuredOptionType: UnionType[Unit] =
    UnionType(
      "physDescStructuredOptions",
      Some("Union of physfacet and dimensions"),
      types = List(PhysfacetType, DimensionsType)
    )

  implicit lazy val RepositoryOptionType: UnionType[Unit] =
    UnionType(
      "RepositoryOptions",
      Some("A union of CorpnameType, FamnameType, NameType and PersnameType"),
      types = List(CorpnameType, FamnameType, NameType, PersnameType)
    )

  implicit lazy val UnitDateStructuredOptionType: UnionType[Unit] =
    UnionType(
      "UnitDateStructuredOptions",
      Some("A Union of datesingle, daterange and dateset types"),
      types = List(DatesingleType, DaterangeType, DatesetType)
    )

  implicit lazy val DimensionsOptionType: UnionType[Unit] =
    UnionType(
      "DimensionsOptions",
      Some("A union of m.mixed.basic.elements and dimensions"),
      types = MixedBasicElementsTypeList :+ DimensionsType
    )

  implicit lazy val RefOptionType: UnionType[Unit] =
    UnionType(
      "RefOptions",
      Some("A union type for all RefOptions"),
      types = List(FreeTextType, AbbrType, CorpnameType, DateType, EmphType, ExpanType, FamnameType, FootnoteType,
        FunctionTypeType, GenreformType, GeognameType, LbType, NameType, NumType, OccupationType, PersnameType,
        PtrType, QuoteType, SubjectType, TitleType)
    )

  implicit val MixedBasicDateElementsOption1Type: UnionType[Unit] =
    UnionType(
      "MixedBasicDateElementsOption1",
      Some("A union of date element options"),
      types = List(FreeTextType, AbbrType, EmphType, ExpanType, ForeignType, LbType, PtrType, RefType)
    )

  implicit lazy val SeriesStmtOptionType: UnionType[Unit] =
    UnionType(
      "SeriesStmtOption",
      Some("A union of seriesStmt option types"),
      types = List(NumType, PType, TitleproperType)
    )

  implicit lazy val EditionStmtOptionType: UnionType[Unit] =
    UnionType(
      "EditionStmtOption",
      Some("A union of edition and p types"),
      types = List(EditionType, PType)
    )

  implicit lazy val PublicationStmtOptionType: UnionType[Unit] =
    UnionType(
      "PublicationStmtOptions",
      Some("A union of PublisherType, DateType, AddressType, NumType, PType"),
      types = List(PublisherType, DateType, AddressType, NumType, PType)
    )

  implicit lazy val LocalControlOptionType: UnionType[Unit] =
    UnionType(
      "LocalControlOptions",
      Some("A union type for LocalControl Options"),
      types = List(DatesingleType, DaterangeType)
    )

  implicit lazy val COrC01Type: UnionType[Unit] =
    UnionType(
      "cOrC01",
      Some("A union of c or c01."),
      types = List(CType, C01Type)
    )

  implicit lazy val BlocksOptionType: UnionType[Unit] =
    UnionType(
      "BlocksOptions",
      Some("A union of ChronlistType, ListTypeType, TableType, BlockquoteType, PType"),
      types = List(ChronlistType, ListTypeType, TableType, BlockquoteType, PType)
    )

  implicit lazy val DesBaseOptionType: UnionType[Unit] =
    UnionType(
      "DesBaseOption",
      Some("A union of AccessrestrictType, AccrualsType, AcqinfoType, AltformavailType, AppraisalType, ArrangementType, " +
        "BibliographyType, BioghistType, ControlaccessType, CustodhistType, FileplanType, IndexType, LegalstatusType," +
        "OddType, OriginalslocType, OtherfindaidType, PhystechType, PreferciteType, ProcessinfoType, " +
        "RelatedmaterialType, RelationsType, ScopecontentType, SeparatedmaterialType, UserestrictType"),
      types = List(AccessrestrictType, AccrualsType, AcqinfoType, AltformavailType, AppraisalType, ArrangementType,
        BibliographyType, BioghistType, ControlaccessType, CustodhistType, FileplanType, IndexType, LegalstatusType,
        OddType, OriginalslocType, OtherfindaidType, PhystechType, PreferciteType, ProcessinfoType,
        RelatedmaterialType, RelationsType, ScopecontentType, SeparatedmaterialType, UserestrictType)
    )


}